package com.winning.pmph.ctrl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.winning.pmph.entity.Resource;
import com.winning.pmph.entity.User;
import com.winning.pmph.service.ResourceService;
import com.winning.pmph.service.RoleService;
import com.winning.pmph.service.UserService;
import com.winning.pmph.utils.ApplicationContextUtil;
import com.winning.pmph.utils.MD5Utils;
import com.winning.pmph.utils.PMPHAppUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.NameValuePair;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.lang.StringUtils;
import org.apache.ibatis.cache.Cache;
import org.apache.ibatis.session.Configuration;
import org.apache.ibatis.session.SqlSessionFactory;
import org.jetbrains.annotations.NotNull;
import org.springframework.cache.CacheManager;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.UUID;
import java.util.stream.Collectors;

/**
 * 登录action
 */
@Api(value = "系统管理/用户管理")
@Slf4j
@RestController
@RequestMapping("/pmph/action/pmph")
public class PMPHLoginCtrl {

    public static final String CRT_USER = "crtUser"; // 当前用户, 存储在sessiono中;

    @javax.annotation.Resource
    private UserService userService;

    @javax.annotation.Resource
    private RoleService roleService;

    @javax.annotation.Resource
    private ResourceService resourceService;

    @ApiOperation(value = "checkUser", notes = "校验用户")
    @PostMapping("checkUser")
    public String checkUser(String JSONResponse,
                            String providerId,
                            HttpServletRequest request,
                            HttpServletResponse response) throws IOException {
        response.setCharacterEncoding("GBK");
        if (StringUtils.isEmpty(JSONResponse) || StringUtils.isEmpty(providerId)) {
            return "<script language=\"javascript\"> "
                    + "alert('请从统一认证平台登录！'); "
                    + "window.close();"
                    + "</script>";
        }
        String url = "https://sso.pmph.com/services/rest/token/verifyJSONResponse";
        HttpClient client = new HttpClient();
        PostMethod method = new PostMethod(url);
        method.addParameter(new NameValuePair("JSONResponse", JSONResponse));
        method.addParameter(new NameValuePair("providerId", providerId));
        client.executeMethod(method);
        JSONObject ssoVerifyResponse = JSON.parseObject(method.getResponseBodyAsString());
        if (!Objects.equals("0x0000", ssoVerifyResponse.getString("status"))) {
            return "<script language=\"javascript\"> "
                    + "alert('" + ssoVerifyResponse.getString("message") + "');"
                    + "window.close();"
                    + "</script>";
        }
        String userName = ssoVerifyResponse.getString("appLoginID");
        User crtUser = userService.getUserByUserName(userName);
        if (crtUser.getStatus() == User.BLOCK) {
            return "<script language=\"javascript\"> "
                    + "alert('该用户已被禁用');"
                    + "</script>";
        }
        request.getSession(true).setAttribute(CRT_USER, crtUser);
        Cookie cookie = new Cookie("from", "sso");
        response.addCookie(cookie);
        response.setCharacterEncoding("UTF-8");
        response.sendRedirect("https://kms.pmphai.com/#/index");
        return "";
    }

    @ApiOperation(value = "syncUser", notes = "sso同步用户接口")
    @PostMapping("syncUser")
    public JSONObject syncUser( String utsNodeInfo) {
        log.debug("++++++++同步用户, 请求参数++++++++" + utsNodeInfo);
        JSONObject requestParamJson = JSON.parseObject(utsNodeInfo);
        JSONObject result = new JSONObject();
        JSONArray resultDatas = new JSONArray();
        JSONObject resultMessage = new JSONObject();
        JSONArray dataArrayJson = requestParamJson.getJSONArray("datas");
        if (Objects.nonNull(dataArrayJson)) {
            for (int i = 0; i < dataArrayJson.size(); i++) {
                JSONObject resultData = new JSONObject();
                JSONObject dataJson = dataArrayJson.getJSONObject(i);
                resultData.put("id", dataJson.getString("id"));
                if (!Objects.equals(dataJson.getString("type"), "person")) {
                    resultData.put("code", "1");
                    resultData.put("message", "只能同步人员信息");
                } else {
                    JSONObject utsNodeJson = dataJson.getJSONObject("utsNode");
                    User dbUser = userService.getUserByUserName(dataJson.getString("oldName"));
                    if (Objects.isNull(dbUser)) {
                        dbUser = new User();
                    }
                    dbUser.setEmailAddress(utsNodeJson.getString("employeemail"));
                    dbUser.setName(utsNodeJson.getString("sn"));
                    dbUser.setPhoneNumber(utsNodeJson.getString("employeemobile"));
                    dbUser.setUserName(dataJson.getString("newName"));
                    userService.saveOrUpdate(dbUser);
                    resultData.put("code", "0");
                    resultData.put("message", "success");
                }
                resultDatas.add(resultData);
            }
        }
        resultMessage.put("datas", resultDatas);
        result.put("status", "0x0000");
        result.put("message", resultMessage);
        return result;
    }

    @ApiOperation(value = "login", notes = "平台登录接口")
    @PostMapping("login")
    public void login(@RequestBody User user, HttpServletRequest request) {
        User crtUser = userService.getUserByUserName(user.getUserName());
        if (Objects.isNull(crtUser)) {
            throw new RuntimeException("用户不存在");
        }
        // 如果用户名密码不匹配;
        HttpSession session = request.getSession(true);
        if (!StringUtils.equals(crtUser.getPassword(), MD5Utils.md5(user.getPassword()))) {
            Integer loginTimes = (Integer) session.getAttribute("loginTimes");
            if (Objects.isNull(loginTimes)) {
                loginTimes = 0;
            }
            session.setAttribute("loginTimes", ++loginTimes);
            if (loginTimes < 5) {
                throw new RuntimeException("用户名或密码错误，还剩" + (5 - loginTimes) + "次用户将被锁定");
            } else {
                crtUser.setStatus(User.BLOCK);
                userService.saveUser(crtUser);
                throw new RuntimeException("该用户被锁定,请联系平台管理员");
            }
        }
        // 判断用户是否锁定;
        if (User.BLOCK.equals(crtUser.getStatus())) {
            throw new RuntimeException("该用户被锁定,请联系平台管理员");
        }
        // 正常登录, 设置session;
        else {
            request.getSession().setAttribute(CRT_USER, crtUser);
        }
    }

    @ApiOperation(value = "selectMenuList", notes = "获取用户菜单接口")
    @GetMapping("selectMenuList")
    public List<Resource> selectMenuList() {
        User user = PMPHAppUtil.getCrtUser();
        List<Resource> resourceList;
        if (Objects.equals("admin", user.getUserName())) {
            resourceList = resourceService.lambdaQuery().orderByAsc(Resource::getSortNum).list();
        } else {
            List<String> roleIdList = user.getRoleIds().toJavaList(String.class);
            resourceList = roleService.selectResourceListByIdList(roleIdList);
        }
        return parseMenuTree(resourceList);
    }

    @NotNull
    private List<Resource> parseMenuTree(List<Resource> resourceList) {
        List<Resource> topMenuList = resourceList.stream()
                .filter(item -> StringUtils.isEmpty(item.getParentId()))
                .collect(Collectors.toList());
        Map<String, Resource> resourceMap = resourceList.stream().collect(Collectors.toMap(Resource::getId, item -> item));
        for (Resource resource : resourceList) {
            if (StringUtils.isNotEmpty(resource.getParentId())) {
                Resource supRes = resourceMap.get(resource.getParentId());
                if (Objects.nonNull(supRes)) {
                    supRes.getChildren().add(resource);
                }
            }
        }
        return topMenuList;
    }

    /**
     * 修改当前用户的密码
     */
    @ApiOperation(value = "changePassWord", notes = "修改当前用户的密码")
    @PostMapping("changePassWord")
    public void changePassWord(String usercode, String oldPassword, String newPassword) {
        User user = userService.login(usercode, MD5Utils.md5(oldPassword));
        if (user == null) {
            throw new RuntimeException("用户名或密码错误");
        } else {
            user.setPassword(MD5Utils.md5(newPassword));
            userService.updateUser(user);
        }
    }

    @ApiOperation(value = "logout", notes = "退出登录接口")
    @GetMapping("logout")
    public void logout(HttpServletRequest request) {
        // 清除session
        request.getSession().invalidate();
    }

    /**
     * 这个接口用于生成一个随机的UUID作为访问验证的公钥。
     */
    @ApiOperation(value = "key", notes = "用于生成一个随机的UUID作为访问验证的公钥")
    @GetMapping("key")
    public String key(HttpServletRequest request) {
        String uuidString = UUID.randomUUID().toString();
        request.getSession().setAttribute("login-verification-keyword", uuidString);
        System.out.println("私钥：" + "f735292e5d7e3a3a2d11d2f1085510ba");
        System.out.println("公钥：" + uuidString);
        System.out.println("token: " + MD5Utils.md5(uuidString + "f735292e5d7e3a3a2d11d2f1085510ba"));
        return uuidString;
    }

    @ApiOperation(value = "selectCrtUser", notes = "获得用户接口")
    @GetMapping("selectCrtUser")
    public Object selectCrtUser(HttpServletRequest request) {
        return request.getSession().getAttribute("crtUser");
    }

    @ApiOperation(value = "deleteMybatisCache", notes = "清除mybatis缓存接口")
    @GetMapping("deleteMybatisCache/{nameSpace}")
    public void deleteMybatisCache(@PathVariable("nameSpace") String nameSpace) {
        Configuration configuration = ApplicationContextUtil.getBean(SqlSessionFactory.class).getConfiguration();
        if (StringUtils.isEmpty(nameSpace)) {
            configuration.getCaches().clear();
            return;
        }
        Cache nameSpaceCache = configuration.getCache(nameSpace);
        if (Objects.nonNull(nameSpaceCache)) {
            nameSpaceCache.clear();
        }
    }

    @ApiOperation(value = "deleteSpringCache", notes = "清除spring缓存接口")
    @GetMapping("deleteSpringCache")
    public void deleteSpringCache() {
        CacheManager cacheManager = ApplicationContextUtil.getBean(CacheManager.class);
        cacheManager.getCacheNames().forEach(item -> cacheManager.getCache(item).clear());
    }
}
